package com.naiterui.ehp.bs.im.task;

import java.util.Date;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import com.naiterui.ehp.bp.utils.date.DateUtil;
import com.naiterui.ehp.bs.im.config.MqttConnectionConfig;
import com.naiterui.ehp.bs.im.network.protocl.SessionDetails;
import com.naiterui.ehp.bs.im.service.message.handler.SessionHandler;

@Service
public class SessionTask implements InitializingBean {

    private static final Logger LOGGER = LoggerFactory.getLogger(SessionTask.class);

    /**
     * 15分钟毫秒数
     */
    private static final long DEFAULT_STEP_15_MM = 900000;

    /**
     * session处理操作类
     */
    private final SessionHandler sessionHandler;

    /**
     * 配置信息
     */
    private final MqttConnectionConfig mqttConnectionConfig;

    /**
     * 会话队列
     */
    private BlockingQueue<SessionDetails> sessionQueue = new LinkedBlockingQueue<>();

    /**
     * sessionId
     */
    private SessionDetails currentSession;

    /**
     * 任务执行失效时间：<code>limitTime</code>
     */
    private long limitTime = System.currentTimeMillis();

    public SessionTask(SessionHandler sessionHandler, MqttConnectionConfig mqttConnectionConfig) {
        this.sessionHandler = sessionHandler;
        this.mqttConnectionConfig = mqttConnectionConfig;
    }

    /**
     * spring容器初始化完成时执行
     */
    @Override
    public void afterPropertiesSet() throws Exception {

        // 启动线程处理sesion队列
        this.autoFinishSession();
    }

    /**
     * 查询出15分钟后满会话周期的未回复的会话记录
     */
    public void doWork(long duration) {

        // 任务触发，刷新任务执行时效
        this.limitTime = System.currentTimeMillis() + duration;

        LOGGER.debug("query have not finished session...");
        // 当前时间
        long currTime = System.currentTimeMillis();

        // 查询截止时间
        long cutOffTime = currTime - (this.mqttConnectionConfig.getSessionTimeout() - DEFAULT_STEP_15_MM);

        // 查询出还有15分钟就要结束的会话
        List<SessionDetails> sessionList = this.sessionHandler.findSessionByTime(cutOffTime);

        // 清空session队列
        this.sessionQueue.clear();

        if (sessionList != null) {
            // 将session信息放入队列处理
            for (SessionDetails session : sessionList) {
                try {
                    // 排除当前正在处理中的session
                    if (!this.isCurrentSession(session)) {
                        this.sessionQueue.put(session);
                    }
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }

    }

    /**
     * 判断session是否是当前正在处理中的session
     */
    public boolean isCurrentSession(SessionDetails session) {

        // 如果当前sessionId相等
        if (this.currentSession != null && this.currentSession.getSessionId().equals(session.getSessionId())) {
            return true;
        }

        return false;
    }

    /**
     * 自动结束复合条件的会话
     */
    public void autoFinishSession() {
        new Thread(() -> {
            // 循环处理队列中的session
            while (true) {
                try {

                    // 取出最早的一条记录
                    this.currentSession = this.sessionQueue.take();

                    while (true) {

                        // 失效任务校验
                        if (this.limitTime <= System.currentTimeMillis()) {
                            this.currentSession = null;
                            this.sessionQueue.clear();
                            LOGGER.info("autoFinishSession overdue : limitTime = {}",
                                    DateUtil.formatDate(new Date(this.limitTime), DateUtil.DATE_TIME_FORMAT));
                            break;
                        }

                        Long endTime = System.currentTimeMillis();

                        long sessionDuraiton = endTime - this.currentSession.getBeginTime();
                        if (sessionDuraiton >= this.mqttConnectionConfig.getSessionTimeout()) {

                            // 如果 session超时执行结束session操作
                            this.sessionHandler.autofinishSession(this.currentSession.getSessionId());

                            LOGGER.debug("auto finish timeout session,sessionId is {}", this.currentSession.getSessionId());

                            break;
                        }

                        Thread.sleep(this.mqttConnectionConfig.getSessionTimeout() - sessionDuraiton);
                    }
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        }).start();

    }

}
